﻿using Microsoft.Extensions.Configuration;
using LaserMark.Models;
using System.IO;

namespace LaserMark.Components.OPTFileResovle
{
    public class OPTStreamConfigurationProvider : StreamConfigurationProvider
    {
        public static OPTContent? OPTContent { get; set; } = new OPTContent();

        public OPTStreamConfigurationProvider(StreamConfigurationSource source) : base(source)
        {
        }

        public static IDictionary<string, string?> Read(Stream stream)
        {
            var data = new Dictionary<string, string?>(StringComparer.OrdinalIgnoreCase);
            using (var reader = new StreamReader(stream))
            {
                string sectionPrefix = string.Empty;

                while (reader.Peek() != -1)
                {
                    string rawLine = reader.ReadLine()!; // Since Peak didn't return -1, stream hasn't ended.
                    string line = rawLine.Trim();

                    // Ignore blank lines
                    if (string.IsNullOrWhiteSpace(line))
                    {
                        continue;
                    }
                    // Ignore comments
                    if (line[0] is ';' or '#' or '/')
                    {
                        continue;
                    }
                    // [Section:header]
                    if (line[0] == '[' && line[line.Length - 1] == ']')
                    {
                        // remove the brackets
                        sectionPrefix = line.AsSpan(1, line.Length - 2).Trim().ToString();
                        continue;
                    }

                    //// key = value OR "value"
                    int separator = line.IndexOf('=');
                    if (separator < 0)
                    {

                    }
                    string key = line.Substring(0, separator).Trim();
                    string value = line.Substring(separator + 1).Trim();
                    if (sectionPrefix == "OPT_Header")
                    {
                        OPTContent!.Header!.GetType().GetProperty(key)!.SetValue(OPTContent!.Header, value);
                    }
                    if (sectionPrefix == "OPT_Signature")
                    {
                        OPTContent!.Signature!.GetType().GetProperty(key)!.SetValue(OPTContent!.Signature, value);
                    }
                    if (sectionPrefix == "OPT_Pattern")
                    {
                        var aaa = Activator.CreateInstance(typeof(OPTPattern));
                        typeof(OPTPattern).GetProperty(key)!.SetValue(aaa, value);
                        while (sectionPrefix == "OPT_Pattern")
                        {
                            var newLine = reader.ReadLine()!;
                            separator = newLine.IndexOf('=');
                            string newKey = newLine.Substring(0, separator).Trim();
                            var type = typeof(OPTPattern).GetProperty(newKey)!.PropertyType;
                            object? val = default;
                            switch (type.Name)
                            {
                                case "Int32":
                                    val = Convert.ToInt32(newLine.Substring(separator + 1).Trim());
                                    break;
                                case "Double":
                                    val = Convert.ToDouble(newLine.Substring(separator + 1).Trim());
                                    break;
                            }
                            typeof(OPTPattern).GetProperty(newKey)!.SetValue(aaa, val ?? newLine.Substring(separator + 1).Trim());

                            if (string.IsNullOrEmpty(newLine))
                            {
                                break;
                            }
                        }
                        OPTContent!.Patterns!.GetType().GetProperty("Patterns")!.SetValue(OPTContent!.Patterns, aaa);
                    }
                }
            }
            return data;
        }

        public override void Load(Stream stream)
        {
            Read(stream);
        }
    }
}
